#include "net.h"


// 进程回收函数
void recyle(int num)
{
    pid_t pid;
    while( (pid = waitpid(-1, NULL, WNOHANG)) > 0 )
    {
        printf("child died , pid = %d\n", pid);
    }
}

int main(int argc, const char *argv[])
{
	int listenfd,connfd;
	struct sockaddr_in servaddr,cliaddr;
	socklen_t peerlen;
	char buf[64];
	int real_read;

	//填充结构体servaddr信息
	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET,SERV_IP_ADDR,(void *)&servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);

	if( -1 == (listenfd = socket(AF_INET,SOCK_STREAM,0)) )
	{//1.建立监听套接字
		perror("socket failed");
		return -1;
	}	
	printf("socket create success....\n");

	if(-1 == bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) )
	{//2.绑定IP和端口信息
		perror("bind failed");
		return -1;
	}
	printf("bind success....\n");

	if( -1 == listen(listenfd,10) )
	{//3.设置端口监听
		perror("listen failed");
		return -1;
	}
	printf("listen success....\n");

    // 6.使用信号回收子进程pcb
    struct sigaction act;
    act.sa_handler = recyle;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGCHLD, &act, NULL);

	bzero(&cliaddr,sizeof(cliaddr));
	peerlen = sizeof(cliaddr);

	while(1)
	{//4.父进程中等待客户端连接

        connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&peerlen);
        while(connfd == -1 && errno == EINTR)
        {//accept阻塞的时候被信号中断
            connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&peerlen);
        }
        printf("connect sucessful\n");
        pid_t pid = fork();
        if (pid == 0)
        {//5.子进程完成与客户端的交互读写文件描述符connfd）
			while(1)
			{

				close(listenfd);	//关闭监听套接字描述符

				bzero(buf,sizeof(buf));
				if( (real_read = read(connfd,buf,sizeof(buf))) < 0)
				{
					perror("recv");
					exit(1);		//终止整个进程
				}
				
				if( 0 == real_read)
				{//客户端断开连接
					close(connfd);
					printf("client break\n");
					break;
				}

				printf("Received: %s\n",buf);

				if( 0 == (strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))) )
				{
					printf("client quit\n");
					break;
				}

				bzero(buf,sizeof(buf));

				printf(">");

				fgets(buf,32,stdin);

				write(connfd,buf,strlen(buf)-1);

				if( 0 == (strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))) )
				{
					printf("client quit\n");
					break;
				}
	        }
	        return 0;	//干掉子进程
	    }
        else if (pid > 0)
        {//父进程
        	close(connfd);		//关闭与客户端通信的套接字描述符
        }
	}
	//
	close(listenfd);
	return 0;
}
